package com.ls.uav_backend.controller;

import cn.hutool.json.JSONUtil;
import com.alibaba.dashscope.app.Application;
import com.alibaba.dashscope.app.ApplicationParam;
import com.alibaba.dashscope.app.ApplicationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.ls.uav_backend.exception.ErrorCode;
import com.ls.uav_backend.exception.ThrowUtils;
import com.ls.uav_backend.model.dto.EnvironmentDataAIChatDTO;
import com.ls.uav_backend.service.AiChatService;
import com.ls.uav_backend.service.ChatHistoryService;
import io.reactivex.Flowable;
import jakarta.annotation.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

@RestController
@RequestMapping("/ai")
public class AiChatController {

    @Resource
    private AiChatService aiChatService;

    @Resource
    private ChatHistoryService chatHistoryService;

    @Resource
    private ApplicationParam.ApplicationParamBuilder<?, ?> applicationParamBuilder;

    @Deprecated
    @GetMapping(value = "/simple/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<ApplicationResult>> simpleChat(@RequestParam String userMessage)
            throws NoApiKeyException, InputRequiredException {

        ApplicationParam param = applicationParamBuilder.prompt(userMessage).build();

        Application application = new Application();
        Flowable<ApplicationResult> flowable = application.streamCall(param);

        // 将 RxJava 2 的 Flowable 转换为 Reactor 的 Flux
        Flux<ApplicationResult> contentFlux = RxJava2Adapter.flowableToFlux(flowable);
        // 统一转换为 ServerSentEvent 类型
        return contentFlux
                // 先将正常数据转换为 SSE 格式
                .map(result -> ServerSentEvent.<ApplicationResult>builder()
                        .data(result)
                        .build())
                // 再追加结束事件（保持相同的泛型类型）
                .concatWith(Mono.just(ServerSentEvent.<ApplicationResult>builder()
                        .event("done")  // 事件类型标识
                        .data(null)     // 结束事件不需要数据
                        .build()));
    }

    @GetMapping(value = "/memory/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<ApplicationResult>> memoryChat(@RequestParam String userMessage,
                                                               @RequestParam Integer chatId,
                                                               @RequestParam(required = false) String environmentData)
            throws NoApiKeyException, InputRequiredException {
        EnvironmentDataAIChatDTO environmentDataAIChatDTO = JSONUtil.toBean(environmentData, EnvironmentDataAIChatDTO.class);
        String userPrompt = aiChatService.formatUserPromptWithEnvironmentData(userMessage, environmentDataAIChatDTO);
        Flux<ApplicationResult> contentFlux = aiChatService.chatWithMemory(userPrompt, chatId);
        // 统一转换为 ServerSentEvent 类型
        return contentFlux
                // 先将正常数据转换为 SSE 格式
                .map(result -> ServerSentEvent.<ApplicationResult>builder()
                        .data(result)
                        .build())
                // 再追加结束事件（保持相同的泛型类型）
                .concatWith(Mono.just(ServerSentEvent.<ApplicationResult>builder()
                        .event("done")  // 事件类型标识
                        .data(null)     // 结束事件不需要数据
                        .build()));
    }

    @GetMapping("/history/chat")
    public List<Message> historyChat(@RequestParam Integer chatId) {
        ThrowUtils.throwIf(chatId == null, ErrorCode.PARAMS_ERROR);
        return chatHistoryService.loadChatHistory(chatId, 10);
    }
}
